import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.mime.image import MIMEImage
from config.settings import EMAIL_CONFIG
from utils.file_operations import file_manager

class EmailSender:
    """邮件发送类"""
    
    def __init__(self):
        self.smtp_server = EMAIL_CONFIG['smtp_server']
        self.smtp_port = EMAIL_CONFIG['smtp_port']
        self.timeout = EMAIL_CONFIG['timeout']
        self.from_email = None
        self.password = None
        
    def set_credentials(self, email, password):
        """设置发件人凭据"""
        self.from_email = email
        self.password = password
    
    def load_credentials_from_file(self, filepath=None):
        """从文件加载凭据"""
        if filepath is None:
            filepath = os.path.join('./autoLoginFile', 'QMailSMTP.pkl')
        
        credentials = file_manager.load_pickle(filepath)
        if credentials and len(credentials) >= 2:
            self.from_email = credentials[0]
            self.password = credentials[1]
            return True
        return False
    
    def send_email(self, to_emails, subject, content, attachments=None, 
                  content_type="plain", images=None):
        """
        发送邮件
        
        Args:
            to_emails: 收件人邮箱列表或逗号分隔的字符串
            subject: 邮件主题
            content: 邮件内容
            attachments: 附件路径列表
            content_type: 内容类型 ("plain" 或 "html")
            images: 图片附件字典 {cid: image_path}
        """
        if not self.from_email or not self.password:
            return False, "请先设置发件人凭据"
        
        try:
            # 创建邮件对象
            msg = MIMEMultipart()
            msg['Subject'] = subject
            msg['From'] = self.from_email
            
            # 处理收件人
            if isinstance(to_emails, list):
                msg['To'] = ', '.join(to_emails)
                recipient_list = to_emails
            else:
                msg['To'] = to_emails
                recipient_list = [email.strip() for email in to_emails.split(',')]
            
            # 添加邮件正文
            if content_type == "html":
                msg.attach(MIMEText(content, 'html', 'utf-8'))
            else:
                msg.attach(MIMEText(content, 'plain', 'utf-8'))
            
            # 添加图片
            if images:
                for cid, image_path in images.items():
                    if os.path.exists(image_path):
                        with open(image_path, 'rb') as img_file:
                            img_data = img_file.read()
                        image = MIMEImage(img_data)
                        image.add_header('Content-ID', f'<{cid}>')
                        image.add_header('Content-Disposition', 'inline')
                        msg.attach(image)
            
            # 添加附件
            if attachments:
                for attachment_path in attachments:
                    if os.path.exists(attachment_path):
                        with open(attachment_path, 'rb') as file:
                            attachment = MIMEApplication(file.read(), 
                                                        Name=os.path.basename(attachment_path))
                        attachment['Content-Disposition'] = f'attachment; filename="{os.path.basename(attachment_path)}"'
                        msg.attach(attachment)
            
            # 连接SMTP服务器并发送
            with smtplib.SMTP(self.smtp_server, self.smtp_port, timeout=self.timeout) as server:
                server.starttls()  # 启用TLS加密
                server.login(self.from_email, self.password)
                server.sendmail(self.from_email, recipient_list, msg.as_string())
            
            return True, "邮件发送成功"
            
        except smtplib.SMTPAuthenticationError:
            return False, "SMTP认证失败，请检查邮箱和授权码"
        except smtplib.SMTPConnectError:
            return False, "无法连接到SMTP服务器"
        except smtplib.SMTPSenderRefused:
            return False, "发件人被拒绝"
        except smtplib.SMTPRecipientsRefused:
            return False, "收件人被拒绝"
        except smtplib.SMTPDataError:
            return False, "SMTP数据错误"
        except Exception as e:
            return False, f"邮件发送失败: {str(e)}"
    
    def send_attendance_report(self, to_emails, report_data, attachments=None):
        """发送考勤报告邮件"""
        subject = "考勤系统报告"
        
        # 创建HTML内容
        html_content = """
        <html>
        <head>
            <style>
                body { font-family: Arial, sans-serif; margin: 20px; }
                .header { background-color: #4CAF50; color: white; padding: 10px; text-align: center; }
                .content { margin: 20px 0; }
                .footer { margin-top: 30px; font-size: 12px; color: #666; }
                table { width: 100%; border-collapse: collapse; margin: 10px 0; }
                th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
                th { background-color: #f2f2f2; }
            </style>
        </head>
        <body>
            <div class="header">
                <h2>智能考勤系统报告</h2>
            </div>
            <div class="content">
                <p>尊敬的管理员，您好！</p>
                <p>这是系统自动生成的考勤报告，请查收。</p>
        """
        
        # 添加报告数据
        if report_data:
            html_content += "<h3>考勤统计</h3><table>"
            for key, value in report_data.items():
                html_content += f"<tr><td><strong>{key}</strong></td><td>{value}</td></tr>"
            html_content += "</table>"
        
        html_content += """
                <p>报告详情请查看附件。</p>
            </div>
            <div class="footer">
                <p>此邮件由智能考勤系统自动发送，请勿回复。</p>
                <p>发送时间: {timestamp}</p>
            </div>
        </body>
        </html>
        """.format(timestamp=report_data.get('timestamp', ''))
        
        return self.send_email(to_emails, subject, html_content, 
                             attachments=attachments, content_type="html")
    
    def send_daily_summary(self, to_emails, summary_data):
        """发送每日摘要邮件"""
        subject = f"考勤系统每日摘要 - {summary_data.get('date', '')}"
        
        content = f"""
尊敬的管理员：

以下是 {summary_data.get('date', '')} 的考勤摘要：

总签到人数: {summary_data.get('total_sign', 0)}
正常签到: {summary_data.get('success_sign', 0)}
迟到: {summary_data.get('late_sign', 0)}
请假: {summary_data.get('free_sign', 0)}
缺勤: {summary_data.get('absent', 0)}

详细数据请查看系统报表。

祝好！
智能考勤系统
        """
        
        return self.send_email(to_emails, subject, content)
    
    def send_warning_email(self, to_emails, warning_type, details):
        """发送警告邮件"""
        subject = f"考勤系统警告 - {warning_type}"
        
        content = f"""
考勤系统检测到以下问题：

警告类型: {warning_type}
详情: {details}

请及时处理。

系统自动发送
        """
        
        return self.send_email(to_emails, subject, content)
    
    def test_connection(self):
        """测试SMTP连接"""
        if not self.from_email or not self.password:
            return False, "请先设置发件人凭据"
        
        try:
            with smtplib.SMTP(self.smtp_server, self.smtp_port, timeout=self.timeout) as server:
                server.starttls()
                server.login(self.from_email, self.password)
                # 发送测试邮件给自己
                test_subject = "SMTP连接测试"
                test_content = "这是一封测试邮件，用于验证SMTP连接配置。"
                server.sendmail(self.from_email, [self.from_email], 
                              f"Subject: {test_subject}\n\n{test_content}")
            
            return True, "SMTP连接测试成功"
            
        except Exception as e:
            return False, f"SMTP连接测试失败: {str(e)}"

class EmailTemplate:
    """邮件模板类"""
    
    @staticmethod
    def get_welcome_template(user_name):
        """欢迎邮件模板"""
        return f"""
亲爱的 {user_name}：

欢迎使用智能考勤系统！

您的账户已成功创建，现在可以开始使用系统的各项功能：

• 面部数据录入
• 在线签到
• 查看考勤记录
• 个人信息管理

如有任何问题，请联系系统管理员。

祝使用愉快！
智能考勤系统团队
        """
    
    @staticmethod
    def get_password_reset_template(user_name, reset_link):
        """密码重置邮件模板"""
        return f"""
亲爱的 {user_name}：

您请求重置密码，请点击以下链接完成密码重置：

{reset_link}

如果这不是您发起的请求，请忽略此邮件。

此链接将在24小时后失效。

智能考勤系统团队
        """
    
    @staticmethod
    def get_monthly_report_template(user_name, report_data):
        """月度报告邮件模板"""
        return f"""
亲爱的 {user_name}：

这是您本月的考勤报告：

出勤天数: {report_data.get('attendance_days', 0)}
迟到次数: {report_data.get('late_count', 0)}
请假天数: {report_data.get('leave_days', 0)}
出勤率: {report_data.get('attendance_rate', '0%')}

感谢您本月的辛勤工作！

智能考勤系统团队
        """

class BulkEmailSender:
    """批量邮件发送类"""
    
    def __init__(self, email_sender):
        self.email_sender = email_sender
        self.sent_count = 0
        self.failed_count = 0
        self.failed_emails = []
    
    def send_bulk_emails(self, email_list, subject, content_template, 
                        attachments=None, delay=1):
        """
        批量发送邮件
        
        Args:
            email_list: 收件人列表，每个元素为字典 {'email': '', 'data': {}}
            subject: 邮件主题
            content_template: 内容模板，可以使用 {key} 格式化
            attachments: 附件列表
            delay: 发送间隔（秒）
        """
        import time
        
        self.sent_count = 0
        self.failed_count = 0
        self.failed_emails = []
        
        for recipient in email_list:
            try:
                # 格式化内容
                email_content = content_template.format(**recipient.get('data', {}))
                
                # 发送邮件
                success, message = self.email_sender.send_email(
                    recipient['email'], subject, email_content, attachments
                )
                
                if success:
                    self.sent_count += 1
                    print(f"成功发送给: {recipient['email']}")
                else:
                    self.failed_count += 1
                    self.failed_emails.append({
                        'email': recipient['email'],
                        'error': message
                    })
                    print(f"发送失败: {recipient['email']} - {message}")
                
                # 延迟发送，避免被当作垃圾邮件
                time.sleep(delay)
                
            except Exception as e:
                self.failed_count += 1
                self.failed_emails.append({
                    'email': recipient.get('email', 'Unknown'),
                    'error': str(e)
                })
                print(f"发送异常: {e}")
        
        return {
            'sent': self.sent_count,
            'failed': self.failed_count,
            'failed_emails': self.failed_emails
        }

# 全局邮件发送实例
email_sender = EmailSender()
bulk_email_sender = BulkEmailSender(email_sender)